package com.helin.helinhealth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.helin.helinhealth.entity.AiQa;
import com.helin.helinhealth.mapper.AiQaMapper;
import com.helin.helinhealth.service.AiService;
import com.helin.helinhealth.utils.AlibabaQwenClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * AI服务实现类
 */
@Slf4j
@Service
public class AiServiceImpl implements AiService {

    @Autowired
    private AiQaMapper aiQaMapper;
    
    @Autowired
    private AlibabaQwenClient qwenClient;
    
    /**
     * 处理用户问题，返回AI回答
     * 
     * <p>
     * 首先尝试从本地知识库中查找答案，如果找不到合适的答案，
     * 则调用阿里通义千问API获取回答。这样可以减少API调用次数，
     * 降低成本并提高响应速度。
     * </p>
     * 
     * @param question 用户问题
     * @return AI回答
     */
    @Override
    public String askQuestion(String question) {
        log.info("收到用户问题: {}", question);
        
        // 对问题进行预处理
        String processedQuestion = preprocessQuestion(question);
        
        // 先尝试从知识库中查找答案
        String answer = queryFromKnowledgeBase(processedQuestion);
        
        // 如果知识库中没有找到答案，则调用阿里通义千问API
        if (answer == null || answer.trim().isEmpty()) {
            log.info("知识库中未找到答案，调用通义千问API");
            answer = qwenClient.askQuestion(processedQuestion);
        }
        
        return answer;
    }
    
    /**
     * 对问题进行预处理
     * 
     * @param question 原始问题
     * @return 处理后的问题
     */
    private String preprocessQuestion(String question) {
        if (question == null) {
            return "";
        }
        
        // 1. 去除首尾空格
        String processed = question.trim();
        
        // 2. 文本规范化（简单处理）
        processed = processed.replaceAll("\\s+", " "); // 将多个空格合并为一个
        
        // 3. 如果问题没有问号结尾，可以根据需要添加
        if (!processed.endsWith("?") && !processed.endsWith("？") && 
            !processed.endsWith("。") && !processed.endsWith(".")) {
            processed = processed + "？";
        }
        
        // 4. 可以进行更多处理，如纠正常见错别字、标准化表达方式等
        
        return processed;
    }
    
    /**
     * 从知识库中查询问题的答案
     * 
     * <p>
     * 根据用户问题在本地知识库中查找匹配的答案。
     * 采用简单的关键词匹配策略，匹配成功后会增加问题的命中次数。
     * </p>
     * 
     * @param question 用户问题
     * @return 知识库中的答案，如未找到返回null
     */
    @Override
    public String queryFromKnowledgeBase(String question) {
        try {
            // 对问题进行预处理
            String processedQuestion = question.trim().toLowerCase();
            
            // 移除常见的停用词和标点符号
            processedQuestion = processedQuestion.replaceAll("[?？!！.。,，;；]", " ")
                                              .replaceAll("\\s+", " ")
                                              .trim();
            
            // 提取问题中的关键词（去除常见虚词）
            List<String> stopWords = List.of("的", "了", "是", "在", "我", "有", "和", "就", "不", "人", "都", "一", "一个", "上", "也", "很", "用", "怎么", "怎样", "如何", "什么", "为什么");
            String[] words = processedQuestion.split("\\s+");
            StringBuilder keywordBuilder = new StringBuilder();
            
            for (String word : words) {
                if (!stopWords.contains(word) && word.length() > 1) {
                    keywordBuilder.append(word).append(" ");
                }
            }
            
            String keywordString = keywordBuilder.toString().trim();
            String[] keywords = keywordString.split("\\s+");
            
            if (keywords.length == 0 && words.length > 0) {
                // 如果关键词提取失败，使用原始分词
                keywords = words;
            }
            
            log.info("用户问题关键词: {}", String.join(", ", keywords));
            
            // 使用动态条件构建查询
            LambdaQueryWrapper<AiQa> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AiQa::getIsDeleted, 0); // 未删除的记录
            
            if (keywords.length > 0) {
                // 创建关键词的不可变副本
                final String[] keywordsFinal = keywords.clone();
                // 使用OR条件搜索每个关键词
                queryWrapper.and(wrapper -> {
                    for (int i = 0; i < Math.min(keywordsFinal.length, 5); i++) {
                        final int idx = i;
                        if (keywordsFinal[idx].length() > 1) {
                            wrapper.or().like(AiQa::getQuestion, keywordsFinal[idx]);
                        }
                    }
                });
            } else {
                // 如果没有提取到有效关键词，则使用原始问题进行模糊匹配
                final String processedQuestionFinal = processedQuestion;
                queryWrapper.like(AiQa::getQuestion, processedQuestionFinal);
            }
            
            queryWrapper.orderByDesc(AiQa::getHitCount); // 按命中次数降序排序
            queryWrapper.last("LIMIT 10"); // 最多获取10条记录
            
            List<AiQa> qaList = aiQaMapper.selectList(queryWrapper);
            
            if (qaList != null && !qaList.isEmpty()) {
                // 对结果进行评分，找出最佳匹配
                AiQa bestMatch = findBestMatch(qaList, keywords, processedQuestion);
                
                // 增加命中次数
                bestMatch.setHitCount(bestMatch.getHitCount() + 1);
                aiQaMapper.updateById(bestMatch);
                
                log.info("从知识库中找到答案: {}", bestMatch.getAnswer());
                return bestMatch.getAnswer();
            }
            
            return null;
        } catch (Exception e) {
            log.error("查询知识库出错", e);
            return null;
        }
    }
    
    /**
     * 查找最佳匹配的答案
     * 
     * @param qaList 候选答案列表
     * @param keywords 提取的关键词
     * @param originalQuestion 原始问题
     * @return 最佳匹配的问答记录
     */
    private AiQa findBestMatch(List<AiQa> qaList, String[] keywords, String originalQuestion) {
        AiQa bestMatch = qaList.get(0); // 默认取第一个
        int highestScore = 0;
        
        for (AiQa qa : qaList) {
            String dbQuestion = qa.getQuestion().toLowerCase();
            int score = 0;
            
            // 1. 关键词匹配分数
            for (String keyword : keywords) {
                if (dbQuestion.contains(keyword)) {
                    // 关键词越长，权重越高
                    score += keyword.length();
                }
            }
            
            // 2. 精确短语匹配加分
            for (int i = 0; i < keywords.length - 1; i++) {
                String phrase = keywords[i] + " " + keywords[i + 1];
                if (originalQuestion.contains(phrase)) {
                    if (dbQuestion.contains(phrase)) {
                        score += 10; // 连续词组匹配加高分
                    }
                }
            }
            
            // 3. 字符串相似度计算
            if (originalQuestion.length() > 5 && dbQuestion.length() > 5) {
                // 计算最长公共子序列相似度
                int lcsLength = calculateLCS(originalQuestion, dbQuestion);
                score += lcsLength * 2;
            }
            
            // 4. 考虑历史命中率
            score += Math.min(qa.getHitCount(), 10); // 最多加10分
            
            if (score > highestScore) {
                highestScore = score;
                bestMatch = qa;
            }
        }
        
        return bestMatch;
    }
    
    /**
     * 计算最长公共子序列长度
     */
    private int calculateLCS(String s1, String s2) {
        int m = s1.length();
        int n = s2.length();
        int[][] dp = new int[m + 1][n + 1];
        
        for (int i = 0; i <= m; i++) {
            for (int j = 0; j <= n; j++) {
                if (i == 0 || j == 0) {
                    dp[i][j] = 0;
                } else if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
                    dp[i][j] = dp[i - 1][j - 1] + 1;
                } else {
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
                }
            }
        }
        
        return dp[m][n];
    }
} 